// 这个模块就是封装axios实例的模块
import axios from 'axios'
import store from '@/store'
import router from '@/router'
import JSONbig from 'json-bigint'
import { reqGetNewToken } from '@/api/user'
// 创建axios实例
const http = axios.create({
  baseURL: 'http://toutiao-app.itheima.net', // 基准地址
  timeout: 3000, // 请求超时时间
  // transformResponse 这个节点是转换响应的数据,如果配置这一项,axios不会处理响应的数据,
  // 需要我们手动处理
  transformResponse: [function(data) {
    // console.log(data)
    // json-bigint 是来处理大数字的遇到大数字就会分割处理， .parse方法 和 stringify
    try {
      // 优化 如果返回的数据是json格式的字符串, 正确转换
      return JSONbig.parse(data)
    } catch {
      // 返回的数据有可能不是json字符串,转换不了 直接返回
      return data
    }
  }]
})
// 添加请求拦截器
// 只要发送请求,就会经过请求拦截器, 可以在拦截器中统一挂载token
http.interceptors.request.use(function(config) {
  console.log('经过了请求拦截器')
  console.log(config) // config是一个对象,包含了发送的请求的信息,里面有一个headers节点,请求头,我们可在这个headers中统一挂载
  console.log(config.headers)
  const token = store.state.user.tokenInfo.token
  // 请求头挂载token
  if (token && !config.headers.Authorization) {
    config.headers.Authorization = `Bearer ${store.state.user.tokenInfo.token}`
  }
  // console.log('拦截器拦截到了请求')
  return config
}, function(error) {
  // Do something with request error
  return Promise.reject(error)
})
// 响应拦截器
// 只要数据响应,就会被响应拦截器拦截
http.interceptors.response.use(function(response) {
  // 只要经过函数1 都是正确的响应,
  // console.log('经过了响应拦截器1')
  // console.dir(response) // 就是响应给客户端的数据,是一个对象
  return response
}, async function(error) {
  // 只要进了函数2,就是失败的响应
  // {"token":"ey5EIagmE","ken":"MD6pyMVE"}
  // console.dir(error) // 响应信息对象, response
  if (error.response.status === 401) {
    // 说明token过期了刷新token , 刷新前有一个前提,必须有refresh_token才能刷新出来一份新token
    // console.log('token过期了, 刷新token')
    const refresh_token = store.state.user.tokenInfo.refresh_token
    if (refresh_token) {
      try {
        // 刷新
        // 发送请求得到新token
        // console.log('刷新一份新的token')
        const { data: { data: { token }}} = await reqGetNewToken()
        // console.log(token) // 返回的新token
        // 经新的token存储在vuex和本地存储
        store.commit('user/setTokenInfo', { token, refresh_token })
        // 将失败请求的携带的token更新成返回的心token才可以
        error.config.headers.Authorization = `Bearer ${token}` // 这一行不加， 会一直刷新token
        // 需要发送上一失败的请求, 在error错误信息对象中,有一个config, 这个config就是之前请求失败的请求,只需要重新发送这个请求即可
        return http(error.config)
      } catch (error) {
        // refresh_token过期了， 只能重新登录
        store.commit('user/removeToken')
        router.push({
          path: '/login',
          query: {
            backto: router.currentRoute.fullPath // 携带当前路由信息的fullPath  currentRoute标识当前路由信息对象 this.$route
          }
        })
      }
    } else {
      // 重新登录 没有refresh_token情况， 重新登录 并且携带之前访问的路由信息，登录成功后原路返回
      // console.log('重新登录')
      // 有必要将错误残留信息(vuex中和本地存储),清除一下(代码严谨性,代码健壮性)
      // 触发vuex中清除tokenInfo的mutation
      store.commit('user/removeToken')
      router.push({
        path: '/login',
        query: {
          backto: router.currentRoute.fullPath // 携带当前路由信息的fullPath  currentRoute标识当前路由信息对象 this.$route
        }
      })
    }
  }
  return Promise.reject(error)
})
export default http

// 大数字问题? js本身没有计算大数的能力, 超出2的53次方
// network response 面板中看到的是真实的响应数据
// 存储在data中 || preview面板中看到的数据是被格式化之后的
// 问题原因: 数据本身在传递过程是以json字符串的方式传递的,但是我们使用的axios,
// axios默认将我们返回的数据做了处理, 将json字符串转换成json对象的格式  JSON.parse(数据)
// 解决方法: 安装 json-bigint  parse和stringify方法
// axios实例中新增配置 transformResponse
